
#include "type.h"
#include "blink_config.h"

#ifndef BLINK_NUM_MAX
#error "BLINK_NUM_MAX NOT HAVE A CONFIG VALUE"
#endif

#define BLINK_STATE_OFF		BLINK_OFF_STATE_DEFINE
#define BLINK_STATE_ON		(!BLINK_STATE_OFF)

#define period			0
#define duty_ration		1
#define count			2
#define blink_times		3
#define state			4
#define finish_state	5
#define offset_max		6

static uint8_t BLINKS[BLINK_NUM_MAX*offset_max];


void blink_on(uint16_t blink_num)
{
	if(blink_num < BLINK_NUM_MAX){
		blink_set_on_config(blink_num);
		blink_num = blink_num*offset_max;
	    BLINKS[blink_num+state] = BLINK_STATE_ON;
	}
}

void blink_off(uint16_t blink_num)
{
	if(blink_num < BLINK_NUM_MAX){
		blink_set_off_config(blink_num);
		blink_num = blink_num*offset_max;
	    BLINKS[blink_num+state] = BLINK_STATE_OFF;
	}
}

void blink_toggle(uint16_t blink_num)
{
	uint8_t temp = blink_num;
	if(blink_num < BLINK_NUM_MAX){
		blink_num = blink_num*offset_max;
		if(BLINKS[blink_num+state] == BLINK_STATE_ON){
			blink_off(temp);
		}
		else{
			blink_on(temp);
		}
	}
}

uint8_t blink_get_state(uint16_t blink_num)
{
	if(blink_num < BLINK_NUM_MAX){
		blink_num = blink_num*offset_max;
    	return BLINKS[blink_num+state];
	}
	else{
		return BLINK_STATE_OFF;
	}
}

//void blink_start(void)
//{
//	BLINKS[j+blink_blink_times = 0;
//}

void blink_stop(uint16_t blink_num)
{
	if(blink_num < BLINK_NUM_MAX){
		blink_num = blink_num*offset_max;
		BLINKS[blink_num+blink_times] = 0;
	}
}

//blink_times = 0xff blink forever
void blink_start(uint16_t blink_num, uint16_t set_period, 
				uint16_t set_duty_ration, uint8_t set_blink_times,
				uint8_t set_finish_state)
{
	uint8_t temp = blink_num;
	if(set_duty_ration > set_period){
		return;
	}
	if(blink_num < BLINK_NUM_MAX){
		blink_num = blink_num*offset_max;
		// if(BLINKS[blink_num+state] == BLINK_STATE_ON){
		// 	blink_off(temp);
		// 	BLINKS[blink_num+count] = set_duty_ration;
		// }
		// else{
			blink_on(temp);
			BLINKS[blink_num+count] = 0;
		// }
		BLINKS[blink_num+period] = set_period;
		BLINKS[blink_num+duty_ration] = set_duty_ration;
		BLINKS[blink_num+blink_times] = set_blink_times;
		BLINKS[blink_num+finish_state] = set_finish_state;
	}
}

uint8_t blink_is_blink(uint16_t blink_num)
{
	if(blink_num < BLINK_NUM_MAX){
		blink_num = blink_num*offset_max;
		return (BLINKS[blink_num+blink_times] == 0)?0:1;
	}
	else{
		return 0;
	}
}

uint8_t blink_check_blink_all(void)
{
	volatile uint8_t i;
	volatile uint16_t j;
    for(i = 0; i < BLINK_NUM_MAX; i++) {
		j = i*offset_max;
		if(BLINKS[j+blink_times] != 0){
			return 1;
		}
	}
	return 0;
}


void blink_init(void) 
{
	volatile uint8_t i;
	volatile uint16_t j;
    for(i = 0; i < BLINK_NUM_MAX; i++) {
		j = i*offset_max;
        BLINKS[j+period] = 0;
        BLINKS[j+duty_ration] = 0;
        BLINKS[j+count] = 0;
		BLINKS[j+blink_times] = 0;
        BLINKS[j+state] = BLINK_STATE_OFF;
        BLINKS[j+finish_state] = BLINK_STATE_OFF;
		blink_off(i);
	}
}

void blink_handler(void)
{
	volatile uint8_t i;
	volatile uint16_t j;

	for (i = 0; i < BLINK_NUM_MAX; i++) {
		j = i*offset_max;
        if(BLINKS[j+blink_times] == 0){
            continue;
        }

		if(BLINKS[j+count] == 0){
			blink_on(i);
		}

		if(BLINKS[j+count] == BLINKS[j+duty_ration]){
			blink_off(i);
			if(BLINKS[j+blink_times] != 0xff){
				BLINKS[j+blink_times]--;
			}
		}

		if(BLINKS[j+count] >= BLINKS[j+period] - 1){
			BLINKS[j+count] = 0;
		}
		else{
			BLINKS[j+count]++;
		}
		if(BLINKS[j+blink_times] == 0){
			BLINKS[j+count] = 0;
			if(BLINKS[j+finish_state] != BLINK_STATE_OFF){
				blink_on(i);
			}
		}
	}
}

